home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 2
/
Amiga Tools 2.iso
/
tools
/
mg
/
src.lzh
/
amiga
/
fileio.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-23
|
14KB
|
638 lines
/*
* Name: MG 2a401 Commodore Amiga file I/O. Last edit: 05-May-88
* swalton@solar.stanford.edu Next-to-Last edit: 16-Dec-87
* mic@emx.utexas.edu Created: 23-Jul-86 mic@emx.utexas.edu
*
* Read and write ASCII files. All of the low level file I/O knowledge is here.
* Uses AmigaDOS standard I/O and does its own dynamic buffering; this seems
* to save about 2K worth of space in the executable image.
*/
#undef LATTICE
#undef MANX
#include "compiler.h"
#include "no_backup.h"
#include "no_startup.h"
#include "no_dir.h"
#include "no_dired.h"
#ifdef LATTICE
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#endif
#include "use_arp.h"
#include "foob.h"
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#ifdef USE_ARP
#include <arpfunctions.h>
#include <libraries/arpbase.h>
#else
#define FCHARS 32L
#endif
#ifdef LATTICE
#include <proto/all.h>
#else
#include <functions.h>
#endif
#undef TRUE
#undef FALSE
#include "def.h"
#include "line.h"
#include "buffer.h"
#ifdef ANSI
#undef EOF
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#ifndef NO_PROTO
char *mktemp PROTO((char *));
#endif
#ifdef LATTICE
#undef LATTICE
#include <dos.h>
#define isdirectory(x) (getfa(x) == 1)
#endif
#define NIOBUF 4096
static VOID FlushBuf PROTO((VOID));
static BPTR ffh = 0;
static UBYTE *iobuf;
static int ibufo, niobuf;
static LONG iostat, access_mode;
#ifdef MANX
extern char *strncpy(), *strncat(), *index(), *rindex();
#endif
#ifdef LATTICE
static void TackOn(char *path, char *file);
#define index strchr
#define rindex strrchr
#endif
#define getch() (ibufo == niobuf) ? FillBuf() : iobuf[ibufo++]
#define putch(c) {if (niobuf == NIOBUF) FlushBuf(); iobuf[niobuf++] = c;}
/*
* Open the Emacs internal file for reading.
*/
ffropen(fn)
char *fn;
{
if ((iobuf = AllocMem((ULONG) NIOBUF, 0L)) == NULL)
return (FIOERR);
if ((ffh = Open(fn, access_mode = MODE_OLDFILE)) == 0L) {
FreeMem(iobuf, (ULONG) NIOBUF);
return (FIOFNF);
}
ibufo = niobuf = 0;
return (FIOSUC);
}
/*
* Open a file for writing. Return TRUE if all is well, and FALSE on error
* (cannot create).
*/
ffwopen(fn)
char *fn;
{
if ((iobuf = AllocMem((ULONG) NIOBUF, 0L)) == NULL)
return (FIOERR);
if ((ffh = Open(fn, access_mode = MODE_NEWFILE)) == 0L) {
ewprintf("Cannot open file for writing");
FreeMem(iobuf, (ULONG) NIOBUF);
return (FIOERR);
}
niobuf = 0;
iostat = NIOBUF; /* pretend we wrote out a full buffer last
* time */
return (FIOSUC);
}
/*
* Close a file, flushing the output buffer. Should look at the status.
*/
ffclose()
{
if (access_mode == MODE_NEWFILE)
FlushBuf();
if (ffh)
(void) Close(ffh);
if (iobuf)
FreeMem(iobuf, (ULONG) NIOBUF);
return (FIOSUC);
}
/*
* Write a buffer to the already opened file. bp points to the buffer. Return
* the status. Check only at the newline and end of buffer.
*/
ffputbuf(bp)
struct buffer *bp;
{
register char *cp;
register char *cpend;
register struct line *lp;
register struct line *lpend;
lpend = bp->b_linep;
lp = lforw(lpend);
do {
cp = <ext(lp)[0]; /* begining of line */
cpend = &cp[llength(lp)]; /* end of line */
while (cp != cpend)
putch(*(cp++)); /* putch only evalutes its arg once */
lp = lforw(lp);
if (lp == lpend)
break; /* no implied newline on last line */
putch('\n');
} while (iostat > 0L);
if (iostat == -1L) {
ewprintf("Write I/O error");
return FIOERR;
}
return FIOSUC;
}
/*
* Read a line from a file, and store the bytes in the supplied buffer. Stop
* on end of file or end of line. When FIOEOF is returned, there is a valid
* line of data without the normally implied \n.
*/
ffgetline(buf, nbuf, nbytes)
register char *buf;
register int nbuf;
register int *nbytes;
{
register int c;
register int i;
i = 0;
while ((c = getch()) != EOF && (c & 0xFF) != '\n') {
buf[i++] = c;
if (i >= nbuf)
return FIOLONG;
}
if (c == EOF && (iostat == -1L)) {
ewprintf("File read error");
return FIOERR;
}
*nbytes = i;
return c == EOF ? FIOEOF : FIOSUC;
}
#ifndef NO_BACKUP
#include "backup_suffix.h"
/*
* Rename the current file into a backup copy, possibly after deleting the
* original file.
*/
fbackupfile(fname)
char *fname;
{
BPTR twiddle, lock;
char buffer[NFILEN];
if (!fname)
return FALSE;
(void) strncpy(buffer, fname, NFILEN - 1);
(void) strcat(buffer, BACKUP_SUFFIX);
lock = Lock(fname, (ULONG) EXCLUSIVE_LOCK); /* does file exist? */
if (!lock)
return (FALSE); /* nope, return error */
twiddle = Lock(buffer, (ULONG) EXCLUSIVE_LOCK);
if (twiddle) { /* delete old backup */
UnLock(twiddle);/* let it go */
if (!DeleteFile(buffer)) {
UnLock(lock);
return (FALSE);
}
twiddle = NULL;
}
/*
* rename file to backup name (after unlocking the file)
*/
UnLock(lock);
return (int) Rename(fname, buffer);
}
#endif /* NO_BACKUP */
#ifdef FOOB
#define DEFAULT_FOOB (0L)
FOOB
getfoob(fname)
char *fname;
{
struct FileInfoBlock *fib;
BPTR lock;
FOOB out;
if (fname == NULL)
return DEFAULT_FOOB;
if ((lock = Lock(fname, ACCESS_READ)) == NULL) /* New file? */
return DEFAULT_FOOB;
if ((fib = (struct FileInfoBlock *)
AllocMem(sizeof(struct FileInfoBlock), 0L)) == NULL) {
ewprintf("Couldn't get %d bytes", sizeof(struct FileInfoBlock));
UnLock(lock);
return DEFAULT_FOOB;
}
if (Examine(lock, fib))
out = fib->fib_Protection;
else {
ewprintf("Couldn't get protection bits for %s", fname);
out = DEFAULT_FOOB;
}
UnLock(lock);
FreeMem(fib, sizeof(struct FileInfoBlock));
return out;
}
void
putfoob(name, mask)
char *name;
FOOB mask;
{
SetProtection(name, mask & ~FIBF_ARCHIVE);
}
#endif
#ifndef NO_STARTUP
/*
* Return name of user's startup file. On Amiga, make it .mg in the current
* directory, then s:mg-startup
*/
static char startname[] = ".mg";
static char altstartname[] = "s:mg-startup";
char *
startupfile()
{
BPTR lock;
if (lock = Lock(startname, (ULONG) SHARED_LOCK)) {
UnLock(lock);
return (startname);
}
if (lock = Lock(altstartname, (ULONG) SHARED_LOCK)) { /* alternate */
UnLock(lock);
return (altstartname);
}
return (NULL);
}
#endif /* NO_STARTUP */
/*
* The string "fn" is a file name. Perform any required name adjustments,
* including conversion to a fully qualified path if NO_DIR isn't defined.
*/
extern char *MyDirName;
char *
adjustname(fn)
register char *fn;
{
#ifndef NO_DIR
static char fnb[MAXPATH];
BPTR lock;
unsigned long PathName();
void TackOn();
char *dup, *p;
if (!fn)
return fn;
if (!index(fn, ':')) { /* no device */
strcpy(fnb, MyDirName);
TackOn(fnb, fn);
if (!index(fn, '/')) /* completely bare name */
return fnb;
} else
strcpy(fnb, fn);
/*
* Else fn has some path components in it. We try to PathName the
* whole thing first, but since the file specified by fn may not
* exist, we PathName the leading part and TackOn the trailing part
* if it doesn't.
*/
if (lock = Lock(fnb, SHARED_LOCK)) {
if (PathName(lock, fnb, (long) MAXPATH) != 0) {
UnLock(lock);
return fnb;
}
ewprintf("adjustname: PathName() failed!");
UnLock(lock);
return fn;
}
if (!(p = rindex(fnb, '/')))
p = index(fnb, ':');
p++;
strcpy((dup = malloc(strlen(p) + 1)), p);
*p = '\0';
if (lock = Lock(fnb, SHARED_LOCK)) {
if (PathName(lock, fnb, (long) MAXPATH) != 0) {
UnLock(lock);
TackOn(fnb, dup);
free(dup);
return fnb;
}
ewprintf("adjustname: PathName() failed!");
UnLock(lock);
}
free(dup);
#endif
return fn; /* if all else fails */
}
/*
* Functions to read/write into the I/O buffer
*/
VOID
FlushBuf()
{
if (niobuf > 0) {
iostat = Write(ffh, iobuf, (long) niobuf);
niobuf = 0;
}
}
/*
* Fill up the input buffer and return the first character in it.
*/
int
FillBuf()
{
if ((iostat = Read(ffh, iobuf, (long) NIOBUF)) <= 0L)
return (EOF);
ibufo = 0;
niobuf = (int) iostat;
return (int) (iobuf[ibufo++]);
}
#ifndef NO_DIRED
#include "kbd.h"
copy(frname, toname)
char *frname, *toname;
{
#ifdef LATTICE
int error;
struct ProcID pid;
if (error = forkl("copy", "copy", frname, toname, NULL, NULL, &pid))
return error;
return (int) wait(&pid);
#else /* MANX (v3.6) or AZTEC (v5.0) */
return fexecl("copy", "copy", frname, toname, (char *) 0);
#endif
}
struct buffer *
dired_(dirname)
char *dirname;
{
register struct buffer *bp;
char line[256];
struct buffer *findbuffer();
char *tmpname, *mktemp();
int i;
VOID lfree();
if ((dirname = adjustname(dirname)) == NULL) {
ewprintf("Bad directory name");
return NULL;
}
if (!isdirectory(dirname)) {
ewprintf("Not a directory: %s", dirname);
return NULL;
}
if ((bp = findbuffer(dirname)) == NULL) {
ewprintf("Could not create buffer");
return NULL;
}
bclear(bp); /* clear out leftover garbage */
(void) strcpy(line, "list >");
(void) strncat(line, tmpname = mktemp("ram:mgXXX.XXX"), sizeof(line));
(void) strncat(line, " \"", sizeof(line));
(void) strncat(line, dirname, sizeof(line));
(void) strncat(line, "\"", sizeof(line));
Execute(line, 0L, 0L);
if (ffropen(tmpname) != FIOSUC) {
ewprintf("Can't open temporary dir file");
return NULL;
}
if (ffgetline(line, sizeof(line), &i) != FIOSUC ||
strncmp(line, "Directory", 9) != 0) {
ffclose();
DeleteFile(tmpname);
ewprintf("No such directory: `%s'", dirname);
return NULL;
}
line[0] = line[1] = ' ';
while (ffgetline(&line[2], sizeof(line) - 3, &i) == FIOSUC) {
line[i + 2] = '\0';
(VOID) addline(bp, line);
}
ffclose();
DeleteFile(tmpname);
bp->b_dotp = lforw(bp->b_linep); /* go to first line */
(VOID) strncpy(bp->b_fname, dirname, NFILEN);
if ((bp->b_modes[0] = name_mode("dired")) == NULL) {
bp->b_modes[0] = &map_table[0];
ewprintf("Could not find mode dired");
return NULL;
}
bp->b_nmodes = 0;
return bp;
}
#ifndef MANX
char *
mktemp(pattern)
char *pattern;
{
/* quick hack mktemp for this purpose only */
register char *name, *printo;
register unsigned short counter = 0;
if (!pattern)
return pattern;
if ((name = malloc(strlen(pattern) + 5)) == NULL)
panic("Manx sucks rocks!");
(VOID) strcpy(name, pattern);
printo = name + strlen(name);
do
(void) sprintf(printo, "%d", counter += 1);
while (counter > 0 && access(name, 0) == 0);
if (counter == 0)
panic("Manx _really_ sucks!");
return name;
}
#endif
#define LIST_LINE_LENGTH 58 /* Size of line from List */
int
d_makename(lp, fn)
register struct line *lp;
register char *fn;
{
register char *cp;
int n = 2;
if (!fn)
return 0;
if (llength(lp) < LIST_LINE_LENGTH)
return ABORT;
if (lgetc(lp, 2) == ':')
return ABORT; /* FileNote line */
(VOID) strcpy(fn, curbp->b_fname);
cp = fn + strlen(fn);
if ((cp[-1] != ':') && (cp[-1] != '/')) /* append '/' if needed */
*cp++ = '/';
while (lgetc(lp, n) != ' ') {
*cp++ = lgetc(lp, n);
n++;
}
*cp = '\0';
return strncmp(&lp->l_text[31], "Dir", 3) == 0;
}
#ifndef LATTICE
static
isdirectory(name)
char *name;
{
long lock;
struct FileInfoBlock *fib;
int result;
if ((lock = Lock(name, ACCESS_READ)) == NULL)
return FALSE;
if ((fib = (struct FileInfoBlock *)
AllocMem((long) sizeof(struct FileInfoBlock), MEMF_PUBLIC)) == NULL) {
UnLock(lock);
return FALSE;
}
result = (fib->fib_DirEntryType > 0L) ? TRUE : FALSE;
FreeMem(fib, (long) sizeof(struct FileInfoBlock));
UnLock(lock);
return result;
}
#endif
#endif
#ifndef USE_ARP
/*
* Here are work-alikes for the few ARP commands now used by the Amiga
* version of mg. These may go away if we require ARP in future.
*/
#ifndef LATTICE
/* Changed because sysdef.h defines stricmp to be Strcmp for non-Lattice
* compilers. This function is required for MANX3.6 and MANX5.0.
*/
Strcmp(s1, s2)
register char *s1, *s2;
{
while (tolower(*s1) == tolower(*s2)) {
if (*s1 == '\0')
return 0;
s1++;
s2++;
}
return (tolower(*s1) < tolower(*s2) ? -1 : 1);
}
#endif
/*
* This PathName function shamelessly stolen from the Matt Dillon Shell. It
* is a slight mod of that program's get_pwd routine, from comm1.c.
*/
unsigned long
PathName(flock, pwdstr, n)
BPTR flock;
char *pwdstr;
long n;
{
char *name;
int err = 0;
BPTR lock, newlock;
struct FileInfoBlock *fib;
int i, len, nentries;
lock = DupLock(flock);
nentries = n / FCHARS;
fib = (struct FileInfoBlock *) AllocMem((long) sizeof(struct FileInfoBlock),
MEMF_PUBLIC);
pwdstr[i = n - 1] = '\0';
while (lock) {
newlock = ParentDir(lock);
if (!Examine(lock, fib))
++err;
name = fib->fib_FileName;
#ifdef V11 /* Actuall, covers V12 also, but */
if (*name == '\0') /* HACK TO FIX RAM: DISK BUG */
name = "RAM";
#endif
len = strlen(name);
if (newlock) {
if (i == n - 1) {
i -= len;
movmem(name, pwdstr + i, len);
} else {
i -= len + 1;
movmem(name, pwdstr + i, len);
pwdstr[i + len] = '/';
}
} else {
i -= len + 1;
movmem(name, pwdstr + i, len);
pwdstr[i + len] = ':';
}
UnLock(lock);
lock = newlock;
}
FreeMem(fib, (long) sizeof(struct FileInfoBlock));
movmem(pwdstr + i, pwdstr, n - i);
if (err)
return (0L);
return ((unsigned long) n - i - 1);
}
static void
TackOn(path, file)
char *path, *file;
{
if (*file != '\0') {
if (path[strlen(path) - 1] != ':')
strcat(path, "/");
strcat(path, file);
}
}
#endif